雖然還是很難過沒辦法拿到完賽證明,但我還是會憑著毅力寫完的QQ
下方程式碼片段全部都是擷取自 Secure Code Warrior 線上安全程式培訓平台,因為練習互動時的題目多半不會只有單一個檔案,可能涉及多個檔案、資料夾及多處地方修改,因此我的文章主要是針對最主要的區塊做修改及說明,若有不好理解的地方非常抱歉也還請見諒,也可以實際上去 Secure Code Warrior 玩玩看,搭配著互動,會更有感的學習哦~
int main(void)
{
char* ptr = (char*)malloc(SIZE);
...
if(err){
free(ptr);
}
...
printf("%s\n",ptr);
}
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
當發生錯誤時釋放記憶體位置的值,但後面又print記體位置導致記憶體損壞
LocationObject *obj;
{
auto instance = std::make_unique<LocationObject> ();
obj = instance.get();
obj->setCallSign(trackValues.at(1));
obj->setParameters(stoi(trackValues.at(2)),stoi(trackValues.at(3)),
stod(trackValues.at(6)),stoi(trackValues.at(5)),
stoi(trackValues.at(4)));
}
tempSituation.push_back(*obj);
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
解釋:
由於unique_ptr
中的託管物件存在於範圍內,根據RAII術語語,在呼叫push_back
時,指標內的物件將不存在。因此,指標obj
也無效。在物件釋出後存取該物件可能會導致程式變得不穩定並崩潰。
將錯誤區塊改成:
LocationObject obj;
obj.setCallSign(trackValues.at(1));
obj.setParameters(stoi(trackValues.at(2)),stoi(trackValues.at(3)),
stod(trackValues.at(6)),stoi(trackValues.at(5)),
stoi(trackValues.at(4)));
tempSituation.push_back(obj);
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
解釋:
建議避免使用 heap 結構記憶體,特別是對於 stack 結構記憶體中不需要太多空間的物件。使用的變數儲存在stack 上,函式完成後,變數本身將被刪除,就不會發生 use-after-free 的條件。
accounts.push_back( account );
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
解釋:accounts
是指向同一account
項目的指標向量。 所有向量的值(指標)都指向同一個項目。 在account
項目被刪除後,這些複製被使用,將導致記憶體存取無效。
將以下區塊:
std::vector< Account* > accounts;
Account* account = new Account();
MSXML::IXMLDOMNodePtr user;
while( ( user = users->nextNode() ) != NULL )
{
bool isName = getNodeValue( user, "name", account->name );
bool isLogin = getNodeValue( user, "login", account->login );
bool isPassword = getNodeValue( user, "password", account->password );
if( !isName || !isLogin || !isPassword )
{
return false;
}
accounts.push_back( account );
}
delete account;
// Add all user records into database.
for( size_t i = 0; i < accounts.size(); i++ )
{
Account* account = accounts[ i ];
std::cout << account->getValues() << std::endl;
db->usersAdd( account );
}
return true
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
改成:
std::vector< Account > accounts;
MSXML::IXMLDOMNodePtr user;
while( ( user = users->nextNode() ) != NULL )
{
Account account;
bool isName = getNodeValue( user, "name", account.name );
bool isLogin = getNodeValue( user, "login", account.login );
bool isPassword = getNodeValue( user, "password", account.password );
if( !isName || !isLogin || !isPassword )
{
return false;
}
accounts.push_back( account );
}
// Add all user records into database.
for( size_t i = 0; i < accounts.size(); i++ )
{
Account* account = &accounts[ i ];
std::cout << account->getValues() << std::endl;
db->usersAdd( account );
}
return true;
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
解釋:accounts
向量保留真實的account
例項,而不僅僅是指標。向量本身控制記憶體分配和重新分配,保護程式免受記憶體洩漏。因此,在這種方法中沒有記憶體洩漏,也沒有釋放的記憶體再次使用。